package gu.sql2java;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import com.google.common.base.Strings;

/**
 * constant declare
 * @author guyadong
 */
public interface Constant {    
	public static final String FIELD_INITIALIZED = "initialized";
	public static final String FIELD_MODIFIED = "modified";
	public static final String FIELD_NEW = "new";

    public static final int STATE_BIT_NUM = 32;
    public static final int STATE_BIT_SHIFT = 5;
    public static final int STATE_BIT_MASK = 0x1f;

    public static final String SQL_LIKE_WILDCARD = "%";
    /** set =QUERY for loadUsingTemplate */
    public static final int SEARCH_EXACT = 0;
    /** set %QUERY% for loadLikeTemplate */
    public static final int SEARCH_LIKE = 1;
    /** set %QUERY for loadLikeTemplate */
    public static final int SEARCH_STARTING_LIKE = 2;
    /** set QUERY% for loadLikeTemplate */
    public static final int SEARCH_ENDING_LIKE = 3;

    /** JDBC property name definition */
    public static enum JdbcProperty{
    	/** alias name of connection */ALIAS("alias"),
        /** debug status */DEBUG("isDebug"),
        /** type of fire listener source:LOCAL,ROW_OBSERVER,default:LOCAL OR null*/FIRE_TYPE("fireType"),
        /** JDBC driver class name */JDBC_DRIVER("jdbc.driver"),
        /** JDBC connection url */JDBC_URL("jdbc.url"),
        /** JDBC user name */JDBC_USERNAME("jdbc.username"),
        /** JDBC password */JDBC_PASSWORD("jdbc.password"),
        /** Retrieval type of auto generated key:auto,before,after */GENERATEDKEY_RETRIEVE("generatedkey.retrieve"),
        /** Retrieval statement of auto generated key */GENERATEDKEY_STATEMENT("generatedkey.statement"),
        /** data source type, C3P0,SQLITE supported only now */DATASOURCE("datasource"),
        /** c3p0 property */C3P0_MINPOOLSIZE("c3p0.minPoolSize"),
        /** c3p0 property */C3P0_MAXPOOLSIZE("c3p0.maxPoolSize"),
        /** c3p0 property */C3P0_MAXIDLETIME("c3p0.maxIdleTime"),
        /** c3p0 property */C3P0_IDLECONNECTIONTESTPERIOD("c3p0.idleConnectionTestPeriod");
        /** JDBC property name */
        public final String key;
        
        JdbcProperty(String key){
            this.key = key;
        }
        /** return {@link #key} with {@code prefix} */
        public String withPrefix(String prefix){
            return new StringBuffer().append(Strings.nullToEmpty(prefix)).append(key).toString();
        }
        /** return true if global property  */
        public boolean isGlobal(){
        	return GLOBAL_PROPS.contains(this);
        }
        /** 全局属性 */
        private static final Set<JdbcProperty> GLOBAL_PROPS;
        private static final HashMap<String, JdbcProperty> KEYS = new HashMap<>();
        static{
        	for(JdbcProperty p: values()){
                KEYS.put(p.key, p);
            }
        	List<JdbcProperty> list = Arrays.asList(DEBUG,ALIAS,FIRE_TYPE,DATASOURCE,GENERATEDKEY_RETRIEVE,GENERATEDKEY_STATEMENT);
        	GLOBAL_PROPS = 
            		Collections.unmodifiableSet(new HashSet<>(list));
        }

        /** 
         * cast {@code key} to {@link JdbcProperty} instance if {@link #key} field equal the argument {@code key},
         * otherwise return {@code null} 
         * @param key JDBC property name
         * @return JdbcProperty
         */
        public static final JdbcProperty fromKey(String key){
            return KEYS.get(key);
        }
        /** 
         * cast {@code key} to {@link JdbcProperty} instance if {@link #key} field equal the argument {@code key},
         * otherwise return {@code null} <br>
         *  be equivalent to {@link #fromKey(String)} if {@code prefix} be {@code null}
         * @param key JDBC property name
         * @param prefix the prefix of key,that will be striped
         * @return JdbcProperty
         */
        public static final JdbcProperty fromKey(String key,String prefix){
        	if(key == null){
        		return null;
        	}
        	int idx;
        	if(prefix != null && (idx = key.indexOf(prefix)) >=0){
        		key = key.substring(idx);
        	}
            return KEYS.get(key);
        }
    }

	/** 
	 * Update strategy for cache
	 * @deprecated replace by {@link com.gitee.l0km.aocache.UpdateStrategy}
	 */
	enum UpdateStrategy{        
	    /** update no matter whether key exists */
	    always,
	    /** update only if key exists */
	    replace,
	    /** remove key  */
	    remove,
	    /** reload data form database if key exists,and update  */
	    refresh;
		public final com.gitee.l0km.aocache.UpdateStrategy aous;
		private UpdateStrategy(){
			aous = com.gitee.l0km.aocache.UpdateStrategy.valueOf(name().toUpperCase());
		}
	}
	/** 
	 * 默认缓存更新策略
     * @deprecated 
	 */
	UpdateStrategy DEFAULT_STRATEGY = UpdateStrategy.remove;
	/** 默认缓存最大缓存容量 */
	long DEFAULT_CACHE_MAXIMUMSIZE = 10000;
	/** 默认缓存失败时间 */
	long DEFAULT_DURATION = 10;
	/** 默认缓存失败时间单位 */
	TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MINUTES;
	public String DEFAULT_ALIAS = "DEFAULT";
	public static final String RETRIEVE_SUFFIX = "generatedkey.retrieve";
	public static final String STATEMENT_SUFFIX = "generatedkey.statement";
	public static final String PAGE_QUERY_SUFFIX = "page.query";
	public static final String INSERT_VALUES_SUFFIX = "insert.values";
	public static final String PRODUCT_NAME_PHOENIX = "Phoenix";
	public static final String PRODUCT_NAME_MYSQL = "MySQL";
	/**
	 * @since 3.34.0
	 */
	public static final String PRODUCT_NAME_SQLite = "SQLite";
	
	
}
